﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace NetJavap.JVM
{
    public static class JVMClassLoader
    {
        private static Dictionary<String, JavaClass> _loadedClasses = new Dictionary<string, JavaClass>();
        private static Dictionary<String, Type> _managedClassTypes = new Dictionary<string, Type>();

        public static JavaClass LoadClass(String fullName)
        {
            JavaClass loadedClass;
            //如果已经装载，则跳过，否则开始装载
            if (!_loadedClasses.TryGetValue(fullName, out loadedClass))
            {
                BinaryReader reader = new BinaryReader(
                           File.OpenRead(Environment.CurrentDirectory + "/" + fullName + ".class"),
                           Encoding.BigEndianUnicode
                           );
               
                Type managedClassType;
                if (_managedClassTypes.TryGetValue(fullName, out managedClassType))
                { 
                    //注册受管制类
                    loadedClass = Activator.CreateInstance(managedClassType, reader) as ManagedJavaClass;
                    var managedClass = loadedClass as ManagedJavaClass;
                    managedClass.InitStatic();
                }
                else
                {
                    loadedClass = new JavaClass(reader);
                }
                _loadedClasses[fullName] = loadedClass;

                //从基类开始调用静态初始化函数来初始化静态函数
                //构造继承结构栈
                Stack<JavaClass> classStack = new Stack<JavaClass>();
                JavaClass currentCls = loadedClass;
                //初始化栈
                while (currentCls != null)
                {
                    classStack.Push(currentCls);
                    currentCls = currentCls.SuperClass;
                }
                //从堆栈顶部开始调用
                currentCls = classStack.Pop();
                while (currentCls!=null)
                {
                    currentCls.InvakeStaticInit();
                    if (classStack.Count == 0)
                    {
                        break;
                    }
                    else
                    {
                        currentCls = classStack.Pop();
                    }
                }
                //调用完成
            }
            return loadedClass;
        }

        public static void RegisterManagedClass<T>(string fullName) where T : ManagedJavaClass
        {
            _managedClassTypes[fullName] = typeof(T);
        }

        static JVMClassLoader()
        {
            RegisterManagedClass<ManagedClasses.PrintStream>(@"java/io/PrintStream");
            RegisterManagedClass<ManagedClasses.System>(@"java/lang/System");
            RegisterManagedClass<ManagedClasses.Sacnner>(@"java/util/Scanner");
        }
    }
}
